Datenvisualisierung mit R

Gestaltungsarten – die “Geome”

15.05.2025

Wo wir waren

ggplot(data = fraktionen_long, 
       aes(x = Partei, y = Anzahl, fill = Geschlecht))+
  geom_col(position = "fill")+
  scale_fill_manual(values = c("red", "blue"))+
  labs(x = NULL, y = "Anteil")

Wie sind die Balken angeordnet?

Reihenfolge der Balken manuell bestimmen – fct_relevel()

Variablen, die nicht Zahlen, sondern Wörter enthalten, sind Faktoren. Standardmäßig werden diese Faktoren alphabetisch sortiert. Deshalb sind die Balken in der Grafik bislang ebenfalls alphabetisch angeordnet.

Um dies zu ändern, verändern wir mithilfe von mutate() und fct_relevel() aus der Bibliothek forcats die Reihenfolge der Parteien im Datensatz.1

fraktionen_long <- fraktionen_long %>%  # in diesem Fall überschreiben wir den Datensatz
  mutate(Partei = fct_relevel(Partei,
                             "DIE LINKE", "GRUENE", "SPD", 
                             "FDP", "CDU/CSU", "AfD"))

Neu sortiert!

ggplot(data = fraktionen_long,
       aes(x = Partei, y = Anzahl, fill = Geschlecht))+
  geom_col(position = "fill")+
  scale_fill_manual(values = c("red", "blue"))+
  labs(x = NULL, y = "Anteil")

fct_relevel() vs fct_reorder()

Mit fct_relevel() können wir jede beliebige Reihenfolge festlegen. Im Beispiel habe ich mich an der Sitzordnung im Bundestag orientiert. Häufig möchten wir aber eine inhaltliche Aussage treffen und die Balken mithilfe von Werten aus einer anderen Variable sortieren – beispielsweise anhand des Frauenanteils in den Fraktionen. Hierfür verwenden wir fct_reorder() ebenfalls aus der forcats-Bibliothek.

Reihenfolge der Balken ändern – fct_reorder()

fraktionen %>%
  mutate(percfem = w/(m + w)) %>% 
  pivot_longer(-c("Partei", "percfem", "id"), names_to = "Geschlecht", values_to = "Anzahl") %>% 
ggplot(aes(x = fct_reorder(Partei, -percfem), y = Anzahl, fill = Geschlecht))+
  geom_col(position = "fill")+
  scale_fill_manual(values = c("red", "blue"))+
  labs(x = NULL, y = "Anteil")

Farben der Parteien hinzufügen

Um die Farben der Parteien festzulegen, kopieren wir Farbcodes von dieser Github-Seite und fügen sie in einen neuen Vektor sein. Verwenden Sie diesen Vektor nun, um die Farben im Diagramm zu ändern. Wie gehen Sie vor?

parteifarbe <- c('#ff748c', '#1AA037', '#E3000F', 
                 '#FFEF00', '#000000', '#0489DB')

Important

Die Reihenfolge der Farben muss den Levels der Variable Partei im Datensatz fraktionen_long entsprechen!

Parteifarben

ggplot(data = fraktionen_long, 
       aes(x = Partei, 
           y = Anzahl, 
           fill = Partei))+
  geom_col(position = "fill")+
  scale_fill_manual(values = parteifarbe)+
  labs(x = NULL, 
       y = "Anteil")

Verwenden Sie nun scale_alpha_manual(), um unterschiedliche Transparenzgrade für Frauen und Männer zu verwenden.

Parteifarben und Transparenz

ggplot(data = fraktionen_long, 
       aes(x = Partei, y = Anzahl, 
           fill = Partei, alpha = Geschlecht))+
  geom_col(position = "fill")+
  scale_fill_manual(values = parteifarbe)+
  scale_alpha_manual(values = c(0.5, 0.9))+
  labs(x = NULL, y = "Anteil")

Fast geschafft!

Um die Farben besser sichtbar zu machen, ändern wir das Erscheinungsbild der Grafik. Das geschieht über theme. Unter anderem folgende Designs sind verfügbar:

theme_bw()

theme_classic()

theme_minimal()

theme_dark()

Minimalistisches Erscheinungsbild

ggplot(data = fraktionen_long, aes(x = Partei, y = Anzahl, 
                                   fill = Partei, alpha = Geschlecht))+
  geom_col(position = "fill")+
  scale_fill_manual(values = parteifarbe)+
  scale_alpha_manual(values = c(0.5, 0.9))+
  labs(x = NULL, y = "Anteil")+
  theme_minimal()

Letzter Schritt

Wir entfernen mit dem Befehl guides() die überflüssige Legende, in der die Parteinamen auftauchen.1

ggplot(data = fraktionen_long, 
       aes(x = Partei, 
           y = Anzahl,
           fill = Partei, 
           alpha = Geschlecht))+
  geom_col(position = "fill")+
  scale_fill_manual(values = parteifarbe)+
  scale_alpha_manual(values = c(0.5, 0.9))+
  labs(x = NULL, y = "Anteil")+
  theme_minimal()+
  guides(fill = FALSE)

Weitere Darstellungsarten

Grammar of Graphics

Weitere “Geome”

Wir werden verschiedene Möglichkeiten kennenlernen, Verteilungen darzustellen. Statt nur den Mittelwert abzubilden, wollen wir alle Werte einer Variable erfassen. Dazu schauen wir uns folgende Darstellungsarten an:

geom_histogram()

geom_density()

geom_point()

geom_jitter()

geom_boxplot()

geom_violin()

Excel-Daten einlesen

Bitte laden Sie die Datei bundestag.xlsx aus dem Order “Datensätze” in Moodle herunter und speichern Sie diese in dem Ordner “data”. Laden Sie ihn mit dem Befehl import():

bundestag <- import(here("data", "bundestag.xlsx"))

Welche Informationen enthält der Datensatz?

'data.frame':   727 obs. of  7 variables:
 $ id         : num  1 2 3 4 5 6 7 8 9 10 ...
 $ vornamen   : chr  "Sanae" "Valentin Christian" "Knut Friedrich Alexander" "Katja" ...
 $ name       : chr  "Abdi" "Abel" "Abraham" "Adler" ...
 $ partei     : chr  "SPD" "FDP" "CDU/CSU" "FDP" ...
 $ geburtsjahr: num  1986 1991 1966 1974 1976 ...
 $ geschlecht : chr  "w" "m" "m" "w" ...
 $ alter      : num  35 30 55 47 45 28 39 31 53 40 ...

Altersverteilung: Histogramm

ggplot(data = bundestag, aes(x = alter))+
  geom_histogram()

Verändern Sie nun die Code, um Frauen und Männer getrennt voneinander darzustellen.

Altersverteilung: Histogramm

ggplot(data = bundestag, aes(x = alter, fill = geschlecht))+
  geom_histogram()

Färben Sie zusätzlich die Außenlinien der Balken weiß ein.

Altersverteilung: Histogramm

ggplot(data = bundestag, aes(x = alter, fill = geschlecht))+
  geom_histogram(color = "white") 

Vielleicht lieber unterschiedliche Farben für die Außenlinien nach Geschlecht verwenden und die Balken selbst weiß einfärben? Als Linienfarbe wählen wir rot und blau.

Altersverteilung: Histogramm

ggplot(data = bundestag, aes(x = alter, color = geschlecht))+
  geom_histogram(fill = "white") +
  scale_color_manual(values = c("red", "blue"))

Histogramm: Balkenbreite

ggplot(data = bundestag, aes(x = alter, color = geschlecht))+
  geom_histogram(fill = "white", binwidth = 0.5) +
  scale_color_manual(values = c("red", "blue"))+
  theme_classic()

Facets

Häufig ist es sinnvoll, nicht alle Gruppen in einer Abbildung darzustellen, sondern eine Abbildung pro Gruppe zu bilden. Dies geschieht über eine weitere Schicht, die wir dem Code hinzufügen.

Die Zeile facet_wrap(~ partei) erzeugt ein Diagramm pro Partei. Nutzen Sie diese Zeile, um die Alterszusammensetzung der Abgeordneten getrennt für die Parteien darzustellen. Auf die Unterscheidung zwischen Frauen und Männern verzichten wir.

Facets

ggplot(data = bundestag, aes(x = alter))+
  geom_histogram()+
  labs(x = NULL)+
  facet_wrap(~ partei)

Density

Lesen Sie sich zunächst die Beschreibung unter ?geom_density durch. Was wird dargestellt?

ggplot(data = bundestag, aes(x = alter, color = geschlecht))+
geom_density()

Experimentieren Sie nun mit fill und alpha.

Density

ggplot(data = bundestag, aes(x = alter, fill = geschlecht, color = geschlecht))+
  geom_density(alpha = 0.4)

Einschub: Die Beschriftung der x-Achse ändern

ggplot(data = bundestag, aes(x = alter, fill = geschlecht, color = geschlecht))+
  geom_density(alpha = 0.4)+
  scale_x_continuous(limits = c(20,80), breaks = c(20,30,40,50,60,70,80))

Die Beschriftung der x-Achse ändern: Alternative

ggplot(data = bundestag, aes(x = alter, fill = geschlecht, color = geschlecht))+
  geom_density(alpha = 0.4)+
  scale_x_continuous(limits = c(20,80), breaks = seq(20, 80, by = 10))

Mehrere Gruppen

ggplot(data = bundestag, aes(x = alter, fill = partei))+
geom_density(alpha = 0.2)

Schön bunt, aber schwierig zu lesen…

Verteilung in Gruppen

Warum ist das keine nützliche Darstellungsart?

ggplot(data = bundestag, aes(x = partei, y = alter))+
  geom_point()+
  labs(x = NULL)

Verteilung in Gruppen – geom_point()

ggplot(data = bundestag, aes(x = partei, y = alter))+
  geom_point(alpha = 0.2)+
  labs(x = NULL)+
  theme_minimal()

Viele Punkte überlagern sich. Das ist nicht ideal. Ersetzen Sie geom_point() durch geom_jitter().

Verteilung in Gruppen – geom_jitter()

ggplot(data = bundestag, aes(x = partei, y = alter, color = partei))+
  geom_jitter(alpha = 0.5, width = 0.1)+ # 'width' bestimmt, wie sehr die Punkte streuen.
  labs(x = NULL)+
  theme_minimal()+
  guides(color = FALSE)

Wir kommen darauf zurück.

Fortsetzung am 05.06.2025!

Session Info

R version 4.5.0 (2025-04-11 ucrt)
Platform: x86_64-w64-mingw32/x64
Running under: Windows 11 x64 (build 26100)

Matrix products: default
  LAPACK version 3.12.1

locale:
[1] LC_COLLATE=German_Germany.utf8  LC_CTYPE=German_Germany.utf8   
[3] LC_MONETARY=German_Germany.utf8 LC_NUMERIC=C                   
[5] LC_TIME=German_Germany.utf8    

time zone: Europe/Berlin
tzcode source: internal

attached base packages:
[1] stats     graphics  grDevices utils     datasets  methods   base     

other attached packages:
 [1] lubridate_1.9.4  forcats_1.0.0    stringr_1.5.1    dplyr_1.1.4     
 [5] purrr_1.0.4      readr_2.1.5      tidyr_1.3.1      tibble_3.2.1    
 [9] tidyverse_2.0.0  ggbeeswarm_0.7.2 ggplot2_3.5.2    flipbookr_0.1.0 
[13] rio_1.2.3        here_1.0.1       pacman_0.5.1    

loaded via a namespace (and not attached):
 [1] generics_0.1.4     stringi_1.8.7      hms_1.1.3          digest_0.6.37     
 [5] magrittr_2.0.3     evaluate_1.0.3     grid_4.5.0         timechange_0.3.0  
 [9] RColorBrewer_1.1-3 fastmap_1.2.0      cellranger_1.1.0   R.oo_1.27.1       
[13] rprojroot_2.0.4    jsonlite_2.0.0     R.utils_2.13.0     scales_1.4.0      
[17] cli_3.6.5          rlang_1.1.6        R.methodsS3_1.8.2  withr_3.0.2       
[21] yaml_2.3.10        tools_4.5.0        tzdb_0.5.0         vctrs_0.6.5       
[25] R6_2.6.1           lifecycle_1.0.4    vipor_0.4.7        pkgconfig_2.0.3   
[29] beeswarm_0.4.0     pillar_1.10.2      gtable_0.3.6       glue_1.8.0        
[33] xfun_0.52          tidyselect_1.2.1   rstudioapi_0.17.1  knitr_1.50        
[37] farver_2.1.2       htmltools_0.5.8.1  rmarkdown_2.29     labeling_0.4.3    
[41] compiler_4.5.0     readxl_1.4.5